package com.whfc.mach.service.impl;

import com.whfc.common.enums.BindFlag;
import com.whfc.common.enums.NetState;
import com.whfc.common.result.ListData;
import com.whfc.common.util.DateUtil;
import com.whfc.fuum.service.SysDeptService;
import com.whfc.mach.dao.AppMachDayMapper;
import com.whfc.mach.dao.AppMachMapper;
import com.whfc.mach.dto.*;
import com.whfc.mach.enums.MachAnaTableColumn;
import com.whfc.mach.enums.WorkState;
import com.whfc.mach.manager.util.MachUtil;
import com.whfc.mach.param.MachMonthDataParam;
import com.whfc.mach.service.AppMachDataAnaService;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;

/**
 * @author qzexing
 * @version 1.0
 * @date 2020-11-09 10:45
 */
@DubboService(interfaceClass = AppMachDataAnaService.class, version = "1.0.0")
public class AppMachDataAnaServiceImpl implements AppMachDataAnaService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private AppMachMapper machMapper;

    @Autowired
    private AppMachDayMapper appMachDayMapper;

    @DubboReference(interfaceClass = SysDeptService.class, version = "1.0.0")
    private SysDeptService sysDeptService;

    @Override
    public MachDataStatDTO getMachInfoData(List<Integer> deptIds) {
        logger.info("获取设备基本统计信息服务,deptIds:{}", deptIds);
        MachDataStatDTO machDataStatDTO = new MachDataStatDTO();

        List<AppMachDTO> machDTOList = machMapper.selectMachList(deptIds, null, null, null, null, null, null, null, null);

        Integer totalNum = machDTOList.size();
        Integer bindNum = 0;
        Integer onlineNum = 0;

        Map<String, Integer> machWorkStateStat1 = new HashMap<>();
        machWorkStateStat1.put(WorkState.STOP.getDesc(), 0);
        machWorkStateStat1.put(WorkState.IDLE.getDesc(), 0);
        machWorkStateStat1.put(WorkState.RUN.getDesc(), 0);
        Map<String, Integer> machTypeStat1 = new HashMap<>();
        Map<String, Integer> machCorpStat1 = new HashMap<>();
        Map<String, Integer> deptStat1 = new HashMap<>();
        Map<Integer, String> map = sysDeptService.getDeptNameMap(deptIds);
        for (AppMachDTO appMachDTO : machDTOList) {
            Integer deptId = appMachDTO.getDeptId();
            String s = map.get(deptId);
            String deptName = s == null ? "未知" : s;
            Integer workState = appMachDTO.getWorkState();
            String machTypeName = appMachDTO.getMachTypeName();
            String corpName = appMachDTO.getCorpName();
            if (StringUtils.isBlank(corpName)) {
                corpName = "未知";
            }
            if (BindFlag.BIND.getValue().equals(appMachDTO.getBindFlag())) {
                bindNum++;
            }
            if (NetState.ONLINE.getValue().equals(appMachDTO.getNetState())) {
                onlineNum++;
                String workStateName = workState == 1 ? WorkState.STOP.getDesc() : workState == 2 ? WorkState.IDLE.getDesc() : workState == 3 ? WorkState.RUN.getDesc() : WorkState.STOP.getDesc();
                machWorkStateStat1.put(workStateName, machWorkStateStat1.get(workStateName) + 1);
            }
            if (machTypeStat1.containsKey(machTypeName)) {
                machTypeStat1.put(machTypeName, machTypeStat1.get(machTypeName) + 1);
            } else {
                machTypeStat1.put(machTypeName, 1);
            }
            if (machCorpStat1.containsKey(corpName)) {
                machCorpStat1.put(corpName, machCorpStat1.get(corpName) + 1);
            } else {
                machCorpStat1.put(corpName, 1);
            }
            if (deptStat1.containsKey(deptName)) {
                deptStat1.put(deptName, deptStat1.get(deptName) + 1);
            } else {
                deptStat1.put(deptName, 1);
            }
        }


        Integer unbindNum = totalNum - bindNum;
        Integer offlineNum = bindNum - onlineNum;
        machWorkStateStat1.put(NetState.OFFLINE.getDesc(), offlineNum);
        machDataStatDTO.setTotalNum(totalNum);
        machDataStatDTO.setBindNum(bindNum);
        machDataStatDTO.setUnbindNum(unbindNum);
        machDataStatDTO.setOnlineNum(onlineNum);
        machDataStatDTO.setOfflineNum(offlineNum);

        List<AppStatNumDTO> machTypeStat = this.getMachStat(machTypeStat1);
        List<AppStatNumDTO> machCorpStat = this.getMachStat(machCorpStat1);
        List<AppStatNumDTO> machWorkStateStat = this.getMachStat(machWorkStateStat1);
        List<AppStatNumDTO> deptStat = this.getMachStat(deptStat1);

        machDataStatDTO.setMachCorpStat(machCorpStat);
        machDataStatDTO.setMachTypeStat(machTypeStat);
        machDataStatDTO.setMachWorkStateStat(machWorkStateStat);
        machDataStatDTO.setDeptStat(deptStat);
        return machDataStatDTO;
    }

    @Override
    public MachRunDataStatDTO getMachRunData(List<Integer> deptIds) {
        logger.info("获取设备运行数据统计服务,deptIds:{}", deptIds);
        MachRunDataStatDTO machRunDataStatDTO = new MachRunDataStatDTO();
        // 7天数据统计
        Date today = DateUtil.getDateBegin(new Date());
        Date startDate = DateUtil.addDays(today, -7);
        Date endDate = DateUtil.addDays(today, -1);
        // 每日数据统计
        List<MachCurveMapDayDTO> list = appMachDayMapper.selectMultiMachCurveMapDayList(deptIds, startDate, endDate);
        for (MachCurveMapDayDTO machCurveMapDayDTO : list) {
            Double operatingRate = MachUtil.computeOperatingRate(machCurveMapDayDTO.getWorkMachNum(), machCurveMapDayDTO.getTotalMachNum());
            machCurveMapDayDTO.setIdleTimes(null);
            machCurveMapDayDTO.setTotalTimes(null);
            machCurveMapDayDTO.setOperatingRate(operatingRate);
        }
        // 昨天的雷达图数据
        Date yesterday = DateUtil.addDays(today, -1);
        MachRadarMapDTO radarMapDTO = appMachDayMapper.selectMultiMachRadarMap(deptIds, yesterday, yesterday);
        radarMapDTO.setGeneralExp(null);
        machRunDataStatDTO.setRadarMapDTO(radarMapDTO);
        machRunDataStatDTO.setList(list);
        return machRunDataStatDTO;
    }

    @Override
    public ListData<AppMachMonthDataDTO> getMonthDataListByType(MachMonthDataParam param) {
        logger.info("获取设备纬度(设备类型)分析数据服务,param:{}", param.toString());
        List<AppMachMonthDataDTO> result = new ArrayList();

        List<Integer> deptIds = param.getDeptIds();
        Map<Integer, String> machTypeMap = param.getMachTypeMap();
        Set<Integer> machTypeIds = machTypeMap.keySet();
        List<Integer> columnIds = param.getColumnIds();
        Date startDate = param.getStartDate();
        Date endDate = param.getEndDate();
        Date startTime = DateUtil.getDateBegin(startDate);
        Date endTime = DateUtil.getDateEnd(endDate);
        // 获得要分析的时间段
        List<Date> dateListBetween = DateUtil.getDateListBetween(startDate, endDate);

        // 查询设备总数
        List<MachDataDTO> totalNumList = appMachDayMapper.selectMachNumTotalByMachType(machTypeIds, deptIds, startTime, endTime);
        // 查询工作设备数
        List<MachDataDTO> workNumList = new ArrayList<>();
        if (columnIds.contains(MachAnaTableColumn.MACHNUMWORK.getValue()) || columnIds.contains(MachAnaTableColumn.MACHNUMIDLE.getValue())) {

            workNumList = appMachDayMapper.selectMachNumWorkByMachType(machTypeIds, deptIds, startTime, endTime);
        }
        // 查找在线设备数/离线设备数
        List<MachDataDTO> onlineNumList = new ArrayList<>();
        if (columnIds.contains(MachAnaTableColumn.MACHNUMONLINE.getValue()) || columnIds.contains(MachAnaTableColumn.MACHNUMOFFLINE.getValue())) {
            onlineNumList = appMachDayMapper.selectMachNumOnlineByMachType(machTypeIds, deptIds, startTime, endTime);
        }
        // 查询设备运行数据
        List<MachDataDTO> machRunDateList = new ArrayList<>();
        if ((columnIds.contains(MachAnaTableColumn.WORKTIMES.getValue())) || (columnIds.contains(MachAnaTableColumn.EFFIC.getValue())) || (columnIds.contains(MachAnaTableColumn.STABEXP.getValue())) || (columnIds.contains(MachAnaTableColumn.EFFICEXP.getValue())) || (columnIds.contains(MachAnaTableColumn.STRENGTHEXP.getValue())) || (columnIds.contains(MachAnaTableColumn.OILEXP.getValue())) || (columnIds.contains(MachAnaTableColumn.SAFEEXP.getValue())) || (columnIds.contains(MachAnaTableColumn.DAYYEILDEXP.getValue())) || (columnIds.contains(MachAnaTableColumn.GENERALEXP.getValue())) || (columnIds.contains(MachAnaTableColumn.OILWEAR.getValue()))) {

            machRunDateList = appMachDayMapper.selectMachRunDataByMachType(machTypeIds, deptIds, startTime, endTime);

        }

        // 数据整合
        this.restructureData(totalNumList, workNumList, onlineNumList, machRunDateList, dateListBetween, machTypeIds, machTypeMap, result);

        return new ListData<>(result);
    }

    @Override
    public ListData<AppMachMonthDataDTO> getMonthDataListByCorp(MachMonthDataParam param) {
        logger.info("获取设备纬度(持有单位)分析数据服务,param:{}", param.toString());
        List<AppMachMonthDataDTO> result = new ArrayList();

        List<Integer> deptIds = param.getDeptIds();
        List<Integer> columnIds = param.getColumnIds();
        Map<Integer, String> corpMap = param.getCorpMap();
        Set<Integer> corpIds = corpMap.keySet();
        Date startDate = param.getStartDate();
        Date endDate = param.getEndDate();
        Date endTime = DateUtil.getDateEnd(endDate);
        Date startTime = DateUtil.getDateBegin(startDate);
        // 获得要分析的时间段
        List<Date> dateListBetween = DateUtil.getDateListBetween(startDate, endDate);

        // 查询设备总数
        List<MachDataDTO> totalNumList = appMachDayMapper.selectMachNumTotalByCorp(corpIds, deptIds, startTime, endTime);
        // 查询工作设备数
        List<MachDataDTO> workNumList = new ArrayList<>();
        if (columnIds.contains(MachAnaTableColumn.MACHNUMWORK.getValue()) || columnIds.contains(MachAnaTableColumn.MACHNUMIDLE.getValue())) {

            workNumList = appMachDayMapper.selectMachNumWorkByCorp(corpIds, deptIds, startTime, endTime);
        }
        // 查找在线设备数/离线设备数
        List<MachDataDTO> onlineNumList = new ArrayList<>();
        if (columnIds.contains(MachAnaTableColumn.MACHNUMONLINE.getValue()) || columnIds.contains(MachAnaTableColumn.MACHNUMOFFLINE.getValue())) {
            onlineNumList = appMachDayMapper.selectMachNumOnlineByCorp(corpIds, deptIds, startTime, endTime);
        }
        // 查询设备运行数据
        List<MachDataDTO> machRunDateList = new ArrayList<>();
        if ((columnIds.contains(MachAnaTableColumn.WORKTIMES.getValue())) || (columnIds.contains(MachAnaTableColumn.EFFIC.getValue())) || (columnIds.contains(MachAnaTableColumn.STABEXP.getValue())) || (columnIds.contains(MachAnaTableColumn.STRENGTHEXP.getValue())) || (columnIds.contains(MachAnaTableColumn.EFFICEXP.getValue())) || (columnIds.contains(MachAnaTableColumn.OILEXP.getValue())) || (columnIds.contains(MachAnaTableColumn.DAYYEILDEXP.getValue())) || (columnIds.contains(MachAnaTableColumn.SAFEEXP.getValue())) || (columnIds.contains(MachAnaTableColumn.GENERALEXP.getValue())) || (columnIds.contains(MachAnaTableColumn.OILWEAR.getValue()))) {

            machRunDateList = appMachDayMapper.selectMachRunDataByCorp(corpIds, deptIds, startTime, endTime);

        }

        // 数据整合
        this.restructureData(totalNumList, workNumList, onlineNumList, machRunDateList, dateListBetween, corpIds, corpMap, result);

        return new ListData<>(result);
    }


    /**
     * 数据整合
     *
     * @param totalNumList
     * @param workNumList
     * @param onlineNumList
     * @param machRunDateList
     * @param dateListBetween
     * @param ids
     * @param nameMap
     * @param result
     */
    private void restructureData(List<MachDataDTO> totalNumList, List<MachDataDTO> workNumList, List<MachDataDTO> onlineNumList, List<MachDataDTO> machRunDateList, List<Date> dateListBetween, Set<Integer> ids, Map<Integer, String> nameMap, List<AppMachMonthDataDTO> result) {
        List<MachDataDTO> list = new ArrayList<>();
        for (Date date : dateListBetween) {
            for (Integer id : ids) {
                MachDataDTO machDataDTO = new MachDataDTO();
                machDataDTO.setId(id);
                machDataDTO.setName(nameMap.get(id));
                machDataDTO.setDate(date);
                machDataDTO.init();
                list.add(machDataDTO);
            }
        }

        for (MachDataDTO machDataDTO : list) {
            this.dataTranslate(totalNumList, machDataDTO);
            this.dataTranslate(workNumList, machDataDTO);
            this.dataTranslate(onlineNumList, machDataDTO);
            this.dataTranslate(machRunDateList, machDataDTO);
        }

        for (Date date : dateListBetween) {
            List<MachDataDTO> dataList = new ArrayList<>();
            for (MachDataDTO data : list) {
                if (data.getDate().equals(date)) {
                    Integer machNumTotal = data.getMachNumTotal();
                    Integer machNumWork = data.getMachNumWork();
                    Integer machNumOnline = data.getMachNumOnline();
                    if (machNumTotal >= machNumWork) {
                        data.setMachNumIdle(machNumTotal - machNumWork);
                    }
                    if (machNumTotal >= machNumOnline) {
                        data.setMachNumOffline(machNumTotal - machNumOnline);
                    }
                    dataList.add(data);
                }
            }

            AppMachMonthDataDTO machMonthDataDTO = new AppMachMonthDataDTO();
            machMonthDataDTO.setDate(DateUtil.formatDate(date));
            machMonthDataDTO.setList(dataList);
            result.add(machMonthDataDTO);
        }
    }


    /**
     * 数据转换
     *
     * @param totalNumList
     * @param target
     */
    private void dataTranslate(List<MachDataDTO> totalNumList, MachDataDTO target) {
        Date date = target.getDate();
        Integer id = target.getId();
        for (MachDataDTO machDataDTO : totalNumList) {
            Integer machNumTotal = machDataDTO.getMachNumTotal();
            Integer machNumWork = machDataDTO.getMachNumWork();
            Integer machNumOnline = machDataDTO.getMachNumOnline();
            Double workTimes = machDataDTO.getWorkTimes();
            Double effic = machDataDTO.getEffic();
            Double stabExp = machDataDTO.getStabExp();
            Double efficExp = machDataDTO.getEfficExp();
            Double strengthExp = machDataDTO.getStrengthExp();
            Double oilExp = machDataDTO.getOilExp();
            Double safeExp = machDataDTO.getSafeExp();
            Double generalExp = machDataDTO.getGeneralExp();
            Double yeildExp = machDataDTO.getYeildExp();
            Double oilWear = machDataDTO.getOilWear();

            if (machDataDTO.getId().equals(id) && machDataDTO.getDate().equals(date)) {
                if (machNumTotal != null) {
                    target.setMachNumTotal(machNumTotal);
                }
                if (machNumWork != null) {
                    target.setMachNumWork(machNumWork);
                }
                if (machNumOnline != null) {
                    target.setMachNumOnline(machNumOnline);
                }
                if (workTimes != null) {
                    target.setWorkTimes(workTimes);
                }
                if (effic != null) {
                    target.setEffic(effic);
                }
                if (stabExp != null) {
                    target.setStabExp(stabExp);
                }
                if (efficExp != null) {
                    target.setEfficExp(efficExp);
                }
                if (strengthExp != null) {
                    target.setStrengthExp(strengthExp);
                }
                if (oilExp != null) {
                    target.setOilExp(oilExp);
                }
                if (safeExp != null) {
                    target.setSafeExp(safeExp);
                }
                if (generalExp != null) {
                    target.setGeneralExp(generalExp);
                }
                if (yeildExp != null) {
                    target.setYeildExp(yeildExp);
                }
                if (oilWear != null) {
                    target.setOilWear(oilWear);
                }

            }
        }

    }


    /**
     * 统计设备数量
     *
     * @param map
     * @return
     */
    private List<AppStatNumDTO> getMachStat(Map<String, Integer> map) {
        List<AppStatNumDTO> list = new ArrayList<>();
        map.forEach((k, v) -> {
            AppStatNumDTO appStatNumDTO = new AppStatNumDTO();
            appStatNumDTO.setName(k);
            appStatNumDTO.setNum(v);
            list.add(appStatNumDTO);
        });
        return list;
    }


}
